﻿using System;
using System.Collections.Generic;
using System.Linq;
using K9Nano.Dependency;
using Microsoft.Extensions.Primitives;

namespace K9Nano.Security
{
    public class Md5UrlSignManager : IUrlSignManager, ISingletonDependency
    {
        protected virtual string Format(IEnumerable<KeyValuePair<string, string>> query)
        {
            var result = string.Join('&', 
                query.OrderBy(x => x.Key).Select(x => $"{x.Key}={x.Value}"));
            return result;
        }

        public virtual string Create(string salt, IDictionary<string, string> query)
        {
            if(string.IsNullOrEmpty(salt)) throw new ArgumentNullException(nameof(salt));

            var formated = Format(query);
            var sign = Md5Helper.ComputeHash(formated + salt);
            return sign;
        }

        public virtual bool Verify(IEnumerable<KeyValuePair<string, StringValues>> query, string salt,
            string signParameter = "sign")
        {
            if (string.IsNullOrEmpty(salt)) throw new ArgumentNullException(nameof(salt));

            var sign = query.FirstOrDefault(x => x.Key == signParameter);
            if (StringValues.IsNullOrEmpty(sign.Value))
            {
                throw new ArgumentException("No sign found");
            }

            var formated = Format(query.Where(x => x.Key != signParameter)
                .OrderBy(x => x.Key)
                .Select(x => new KeyValuePair<string, string>(x.Key, x.Value)));
            var result = Md5Helper.Validate(formated + salt, sign.Value);
            return result;
        }

        public virtual bool Verify(string query, string salt, string signParameter = "sign")
        {
            if (string.IsNullOrEmpty(query)) throw new ArgumentNullException(nameof(query));
            if (string.IsNullOrEmpty(salt)) throw new ArgumentNullException(nameof(salt));

            var index = query.IndexOf("&" + signParameter);
            if (index < 0)
            {
                throw new ArgumentException("No sign found");
            }

            var head = query.Substring(0, index);
            var sign = query.Substring(index + 6); // 不包含"&sign="
            var result = Md5Helper.Validate(head + salt, sign);
            return result;
        }
    }
}